package com.jp.xml.asn1;

import java.io.*;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;


public class SAXEventDumper extends DefaultHandler
{

 public SAXEventDumper()
 {
     out = new PrintWriter(System.out);
     xmlVersion = null;
     xmlEncoding = null;
     dtdName = null;
     dtdFileName = null;
     format = true;
     init();
 }

 public void init()
 {
     isHead = true;
     tab = 0;
     event = -1;
 }

 public void setFormat(boolean format)
 {
     this.format = format;
 }

 public void setWriter(Writer out)
 {
     this.out = out;
 }

 public void setXMLDeclaration(String version, String encoding)
 {
     xmlVersion = version;
     xmlEncoding = encoding;
 }

 public void setDoctypeDeclaration(String name, String fileName)
 {
     dtdName = name;
     dtdFileName = fileName;
 }

 public void startDocument()
     throws SAXException
 {
     try
     {
         if(xmlVersion != null)
         {
             out.write(sep() + tab() + "<?xml version=\"" + xmlVersion + "\"");
             if(xmlEncoding != null)
                 out.write(" encoding=\"" + xmlEncoding + "\"");
             out.write("?>");
             out.flush();
             isHead = false;
         }
         if(dtdName != null)
         {
             out.write(sep() + tab() + "<!DOCTYPE " + dtdName + " SYSTEM \"" + dtdFileName + "\">");
             out.flush();
             isHead = false;
         }
//    	 out.write(System.getProperty("line.separator"));
    	 out.flush();
    	 event = 0;
     }
     catch(Exception e)
     {
         throw new SAXException(e);
     }
 }

 private String sep()
 {
     if(!format)
         return "";
     String sep = SEP;
     if(isHead)
         sep = "";
     return sep;
 }

 private String tab()
 {
     if(!format)
         return "";
     StringBuffer buf = new StringBuffer();
     for(int i = 0; i < tab; i++)
         buf.append(" ");

     return buf.toString();
 }

 public void endDocument()
     throws SAXException
 {
     try
     {
         out.write(sep());
         out.flush();
         event = 3;
     }
     catch(Exception e)
     {
         throw new SAXException(e);
     }
 }

 public void startElement(String uri, String localName, String name, Attributes atts)
     throws SAXException
 {
     try
     {
         out.write(sep() + tab() + "<" + name);
         int i = 0;
         for(int l = atts.getLength(); i < l; i++)
             out.write(" " + atts.getQName(i) + "=\"" + atts.getValue(i) + "\"");

         out.write(">");
         out.flush();
         
         isHead = false;
         tab += 2;
         event = 1;
     }
     catch(Exception e)
     {
         throw new SAXException(e);
     }
 }

 public void endElement(String uri, String localName, String name)
     throws SAXException
 {
     try
     {
         tab -= 2;
         switch(event)
         {
         case 1: // '\001'
         case 2: // '\002'
             out.write("</" + name + ">");
        	 //out.write(",");
             out.flush();
             break;

         default:
             out.write(sep() + tab());
             out.write("</" + name + ">");
         	 out.write(System.getProperty("line.separator"));
             out.flush();
             break;
         }
         event = 3;
     }
     catch(Exception e)
     {
         throw new SAXException(e);
     }
 }

 public void characters(char chars[], int start, int length)
     throws SAXException
 {
     try
     {
         out.write(replaceChars(chars, start, length));
         out.flush();
         event = 2;
     }
     catch(Exception e)
     {
         throw new SAXException(e);
     }
 }

 private String replaceChars(char chars[], int start, int length)
 {
     StringBuffer buf = new StringBuffer();
     for(int i = start; i < start + length; i++)
     {
         char c;
         switch(c = chars[i])
         {
         case 38: // '&'
             buf.append("&amp;");
             break;

         case 60: // '<'
             buf.append("&lt;");
             break;

         default:
             buf.append(c);
             break;
         }
     }

     return buf.toString();
 }

 
 private static final String SEP = System.getProperty("line.separator");
 private static final int UNKNOWN = -1;
 private static final int START_DOCUMENT = 0;
 private static final int START_ELEMENT = 1;
 private static final int CHARACTERS = 2;
 private static final int END_X = 3;
 private Writer out;
 private String xmlVersion;
 private String xmlEncoding;
 private String dtdName;
 private String dtdFileName;
 private boolean format;
 private boolean isHead;
 private int tab;
 private int event;

}